#include <iostream>
#include <sstream>
#include <string>
#include <cassert>

template <typename Char>
using anystring =
    std::basic_string<Char, std::char_traits<Char>, std::allocator<Char>>;

template <typename Char>
using anysstream =
    std::basic_stringstream<Char, std::char_traits<Char>, std::allocator<Char>>;

template <typename Char>
anystring<Char> capitalize(const anystring<Char>& text)
{
    anysstream<Char> ret;
    bool new_word = true;
    for (auto const& c : text)
    {
        new_word = new_word || std::ispunct(c) || std::isspace(c);
        if (std::isalpha(c))
        {
            if (new_word)
            {
                ret << static_cast<Char>(std::toupper(c));
                new_word = false;
            }
            else
            {
                ret << static_cast<Char>(std::tolower(c));
            }
        }
        else
        {
            ret << c;
        }
    }
    return ret.str();
}

#define TEST(exp, txt)                                                        \
    do                                                                        \
    {                                                                         \
        std::wcout << "Testing \"" << txt << "\" expecting: " << exp << '\n'; \
        assert(exp == capitalize(txt));                                       \
        std::cout << "Passed\n";                                              \
    } while (0)

int main(int argc, char** argv)
{
    using namespace std::string_literals;
    std::string text = "THIS IS AN EXAMPLE";
    std::string expect = "This Is An Example";
    std::cout << "Testing \"" << text << "\" expecting: " << expect << '\n';
    assert(expect == capitalize(text));
    std::cout << "passed\n";
    TEST(L"The Handy Snippets"s, L"the handy snippets"s);
    TEST(L"It, Should, Work!"s, L"iT, sHOULD, wORK!"s);
    return 0;
}